using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace GameProject
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        public GraphicsDeviceManager graphics;
        public SpriteBatch spriteBatch;
        Player player = new Player();
        Enemy enemy = new Enemy();
        Bullets bullet = new Bullets();
        Map map = new Map();
        Monument monument = new Monument();
        Texture2D startButton;
        Texture2D exitButton;
        Texture2D gameOverSprite;
        Texture2D titleSprite;
        Vector2 titleSpritePosition;
        Vector2 startButtonPosition;
        Vector2 exitButtonPosition;
        SpriteFont spriteFont;
        Vector2 gameOverPosition;
        private float x, y;
        KeyboardState keyState;
        MouseState mouseState;
        MouseState prevMouseState;
        enum Gamestate
        {
            startMenu,
            round,
            roundBreak,
            pauseMenu,
            gameOver
        }
        Gamestate gameState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferHeight = 801;
            graphics.PreferredBackBufferWidth = 1001;
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            this.IsMouseVisible = true;
            startButtonPosition = new Vector2((GraphicsDevice.Viewport.Width / 2) - 120, 395);
            exitButtonPosition = new Vector2((GraphicsDevice.Viewport.Width / 2) - 120, 490);
            
            map.Initialize();
            monument.Initialize();
            player.Initialize();
            bullet.Initialize();
            enemy.Initialize();
            gameState = Gamestate.startMenu;
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            startButton = Content.Load<Texture2D>("newGame");
            exitButton = Content.Load<Texture2D>("exitGame");
            titleSprite = Content.Load<Texture2D>("titleSprite");
            gameOverSprite = Content.Load<Texture2D>("gameOverSprite");
            spriteFont = Content.Load<SpriteFont>("SpriteFont1");
            spriteFont = Content.Load<SpriteFont>("SpriteFont2");
            gameOverPosition = new Vector2((GraphicsDevice.Viewport.Width / 2) - gameOverSprite.Width / 2, 350);
            titleSpritePosition = new Vector2((GraphicsDevice.Viewport.Width / 2) - titleSprite.Width / 2, 150);
            map.LoadContent(Content);
            monument.LoadContent(Content);
            player.LoadContent(Content);
            enemy.LoadContent(Content);
            bullet.LoadContent(Content);
            base.LoadContent();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if ((GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                || (Keyboard.GetState().IsKeyDown(Keys.Escape)))
            {
                this.Exit();
            }
            else if (gameState == Gamestate.roundBreak || gameState == Gamestate.round)
            {
                movePlayer(gameTime);
                enemy.Update(gameTime, monument, player);
                bullet.Update(gameTime, player, map);
                bulletEnemyCollision();
                bulletMonumentCollision();
                if (monument.getHealth() <= 0)
                {
                    gameState = Gamestate.gameOver;
                }
            }
            
            mouseState = Mouse.GetState();
            
            if(prevMouseState.LeftButton == ButtonState.Pressed && 
                mouseState.LeftButton == ButtonState.Released)
            {
                mouseClick(mouseState.X, mouseState.Y);
            }            
            monument.Update(gameTime);
            player.Update(gameTime);
            prevMouseState = mouseState;
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DarkSeaGreen);
            spriteBatch.Begin();
            if(gameState == Gamestate.startMenu)
            {
                spriteBatch.Draw(startButton, startButtonPosition, Color.White);
                spriteBatch.Draw(exitButton, exitButtonPosition, Color.White);
                spriteBatch.Draw(titleSprite, titleSpritePosition, Color.White);
            }
            else if (gameState == Gamestate.roundBreak || gameState == Gamestate.round || gameState == Gamestate.gameOver)
            {
                map.Draw(spriteBatch);
                monument.Draw(spriteBatch);
                player.Draw(spriteBatch);
                enemy.Draw(spriteBatch);
                bullet.Draw(spriteBatch, player);
                if(gameState == Gamestate.gameOver)
                {
                    spriteBatch.Draw(gameOverSprite, gameOverPosition, Color.White);
                    spriteBatch.DrawString(spriteFont, "Final Score: " + player.getPoints().ToString(), new Vector2(345, 425), Color.Black);
                }
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }
        public void movePlayer(GameTime gameTime)
        {
            x = player.getPlayerX();
            y = player.getPlayerY();
            keyState = Keyboard.GetState();
            float sideMovementSpeed = 0.65f;
            if (gameState != Gamestate.gameOver)
            {
                if (keyState.IsKeyDown(Keys.W) && keyState.IsKeyDown(Keys.A) 
                    && keyState.IsKeyDown(Keys.S) && keyState.IsKeyDown(Keys.D))
                {

                }
                else if (keyState.IsKeyDown(Keys.W) && keyState.IsKeyDown(Keys.A) 
                    && (map.checkCollisionAll(player.getPlayerX() - 3, player.getPlayerY() - 3)))//Move Up and Left
                {
                    player.setPlayerY(y -= (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                    player.setPlayerX(x -= (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.W) && keyState.IsKeyDown(Keys.D) 
                    && (map.checkCollisionAll(player.getPlayerX() + 3, player.getPlayerY() - 3)))//Move Up and Right
                {
                    player.setPlayerY(y -= (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                    player.setPlayerX(x += (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.S) && keyState.IsKeyDown(Keys.D) 
                    && (map.checkCollisionAll(player.getPlayerX() + 3, player.getPlayerY() + 3)))//Move Down and Right
                {
                    player.setPlayerY(y += (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                    player.setPlayerX(x += (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.S) && keyState.IsKeyDown(Keys.A) 
                    && (map.checkCollisionAll(player.getPlayerX() - 3, player.getPlayerY() + 3)))//Move Down and Left
                {
                    player.setPlayerY(y += (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                    player.setPlayerX(x -= (player.getMovementSpeed() * sideMovementSpeed) * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.W) && (map.checkCollisionAll(player.getPlayerX(), player.getPlayerY() - 3)))//Move up
                {
                    player.setPlayerY(y -= player.getMovementSpeed() * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.D) && (map.checkCollisionAll(player.getPlayerX() + 3, player.getPlayerY())))//Move Right
                {
                    player.setPlayerX(x += player.getMovementSpeed() * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.A) && (map.checkCollisionAll(player.getPlayerX() - 3, player.getPlayerY())))//Move Left
                {
                    player.setPlayerX(x -= player.getMovementSpeed() * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
                else if (keyState.IsKeyDown(Keys.S) && (map.checkCollisionAll(player.getPlayerX(), player.getPlayerY() + 3)))//Move Down
                {
                    player.setPlayerY(y += player.getMovementSpeed() * (float)gameTime.ElapsedGameTime.TotalSeconds);
                }
            }
        }

        public void mouseClick(int x, int y)
        {
            Rectangle mouseClickRectangle = new Rectangle(x, y, 1, 1);
            if (gameState == Gamestate.startMenu)
            {
                Rectangle startGameHitBox = new Rectangle((int)startButtonPosition.X,
                    (int)startButtonPosition.Y, 247, 70);
                Rectangle exitGameHitBox = new Rectangle((int)exitButtonPosition.X,
                    (int)exitButtonPosition.Y, 247, 70);


                if (mouseClickRectangle.Intersects(startGameHitBox))
                {
                    gameState = Gamestate.roundBreak;
                    
                }
                else if (mouseClickRectangle.Intersects(exitGameHitBox))
                {
                    Exit();
                }
            }
        }
        public void bulletEnemyCollision()
        {
            Rectangle tempBullet;
            Rectangle tempEnemy;
            for (int i = 0; i < bullet.bulletList.Count; i++)
			{
			    for (int j = 0; j < enemy.enemyList.Count; j++)
			    {
                    tempBullet = bullet.bulletList[i].getBulletHitBox();
                    tempEnemy = enemy.enemyList[j].getEnemyHitBox();
                    if (tempBullet.Intersects(tempEnemy))
                    {
                        enemy.enemyList[j].damageHealth(bullet.getBulletDamage());
                        bullet.bulletList.RemoveAt(i);
                        break;
                    }
			    }
			}
        }
        public void bulletMonumentCollision()
        {
            Rectangle tempBullet;
            Rectangle tempMonument;
            for (int i = 0; i < bullet.bulletList.Count; i++)
            {
                tempBullet = bullet.bulletList[i].getBulletHitBox();
                tempMonument = monument.getHitBox();
                if (tempBullet.Intersects(tempMonument))
                {
                    monument.damageToHealth(-1);
                    bullet.bulletList.RemoveAt(i);
                    break;
                }
            }
        }
    }
}
